package com.recharge.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.recharge.common.annotation.OperationLogDetail;
import com.recharge.common.domain.PageDO;
import com.recharge.common.enums.ErrorCode;
import com.recharge.common.enums.OperationLogType;
import com.recharge.common.result.ResultDO;
import com.recharge.common.util.BeanUtilsExtends;
import com.recharge.common.util.Constant;
import com.recharge.common.util.SnowflakeIdWorker;
import com.recharge.common.util.TemplateUtils;
import com.recharge.core.entity.RefundEntity;
import com.recharge.core.mapper.RefundMapper;
import com.recharge.domain.query.RefundQueryDO;
import com.recharge.domain.vo.MerchantAccountDO;
import com.recharge.domain.vo.RefundDO;
import com.recharge.domain.vo.TransactionDO;
import com.recharge.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 退款单 服务实现类
 * </p>
 *
 * @author reagan
 * @since 2020-08-19
 */
@Service
public class RefundServiceImpl extends ServiceImpl<RefundMapper, RefundEntity> implements RefundService {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Value("${node.name}")
    private Integer nodeName;

    @Autowired
    MerchantService merchantService;
    @Autowired
    MerchantAccountService merchantAccountService;
    @Autowired
    OrderService orderService;
    @Autowired
    GoodsService goodsService;
    @Autowired
    TransactionService transactionService;

//    @Override
//    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
//    public ResultDO add(RefundDO domain) {
//
//        String refundNo = SnowflakeIdWorker.getNo();
//
//        TransactionDO transactionDO = new TransactionDO();
//
//        transactionDO.setIdentifierNo(refundNo);
//        transactionDO.setTransactionNo(SnowflakeIdWorker.getNo());
//        transactionDO.setAmount(domain.getAmount());
//        transactionDO.setAmountType(Constant.INCOME);
//        transactionDO.setMerchantNo(domain.getMerchantNo());
//        transactionDO.setType(Constant.TRANSACTION_TYPE_4);
//        transactionDO.setBeginDate(Calendar.getInstance().getTime());
//        transactionDO.setBeforeBalance(domain.getBeforeBalance());
//        transactionDO.setBalance(domain.getAfterBalance());
//
//        RefundEntity entity = new RefundEntity();
//
//        ResultDO result = BeanUtilsExtends.copy(entity, domain);
//        if (!result.isSuccess()) {
//            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
//            return result;
//        }
//
//        entity.setRefundDate(Calendar.getInstance().getTime());
//        entity.setRefundNo(refundNo);
//
//        boolean res = false;
//        try {
//            res = this.save(entity);
//        } catch (Exception e) {
//            result.setSuccess(false);
//            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
//            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
//            return result;
//        }
//
//        //判断r的值是否小于0.如果小于0 就代表添加失败
//        if (!res) {
//            result.setSuccess(false);
//            result.setErrorCode(ErrorCode.REFUND_USER_STATUS_ERROR);
//            logger.debug("error code：" + ErrorCode.REFUND_USER_STATUS_ERROR.getCode() + " msg" + ErrorCode.REFUND_USER_STATUS_ERROR.getMsg());
//            return result;
//        }
//
//        result = transactionService.add(transactionDO);
//        if (!result.isSuccess()){
//            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return result;
//        }
//        result.setModel(ResultDO.FIRST_MODEL_KEY, getDomain(entity));
//        return result;
//    }

    @Override
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    @OperationLogDetail(operationType = OperationLogType.ADD, detail = "退款操作")
    public ResultDO submit(RefundDO domain) {
        // 创建实体类
        RefundEntity entity = new RefundEntity();
        TransactionDO transactionDO = new TransactionDO();

        // 拷贝数据
        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        //判断是否拷贝成功
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        MerchantAccountDO merchantAccountDO = null;
        try {
            merchantAccountDO = (MerchantAccountDO) merchantAccountService.get(domain.getMerchantId()).getModel(ResultDO.FIRST_MODEL_KEY);
        } catch (Exception e) {
            logger.debug(e.getMessage());
        }
        if (merchantAccountDO == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.MERCHANT_INFO_ERROR);
            logger.debug("退款查询代理商信息失败");
            return result;
        }

        /*
         * 1.修改余额
         * 2.添加交易记录
         * 3.添加退款记录
         */
        result = merchantAccountService.editBalance(entity.getMerchantId(), entity.getAmount());
        if (!result.isSuccess()) {
            logger.debug("修改余额失败");
            result.setErrorCode(ErrorCode.MERCHANT_EDIT_ACCOUNT_ERROR);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }
        Long before = (Long) result.getModel(ResultDO.FIRST_MODEL_KEY);
        Long after = (Long) result.getModel(ResultDO.SECOND_MODEL_KEY);

        transactionDO.setAmount(domain.getAmount());
        transactionDO.setBeforeBalance(before);
        transactionDO.setBalance(after);
        transactionDO.setStatus(Constant.TRANSACTION_STATUS_1);
        transactionDO.setTransactionNo(SnowflakeIdWorker.getNo());
        transactionDO.setIdentifierNo(SnowflakeIdWorker.getNo());
        transactionDO.setAmountType(Constant.INCOME);
        transactionDO.setNodeName(nodeName);
        transactionDO.setType(Constant.TRANSACTION_TYPE_4);
//        transactionDO.setMerchantName(domain.getMerchantName());
        transactionDO.setMerchantNo(domain.getMerchantNo());
        transactionDO.setGoodsName(domain.getGoodsTitle());
        transactionDO.setAccountNo(merchantAccountDO.getAccountNo());
        transactionDO.setStatus(Constant.TRANSACTION_STATUS_1);
        result = transactionService.add(transactionDO);
        if (!result.isSuccess()) {
            logger.debug("添加交易记录失败");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }
        transactionDO = (TransactionDO) result.getModel(ResultDO.FIRST_MODEL_KEY);

//        RefundEntity entity = new RefundEntity();
//        entity.setAmount(domain.getAmount());
//        entity.setMerchantId(domain.getMerchantId());
//        entity.setType(domain.getType());
//        entity.setRemark(domain.getRemark());
        entity.setRefundDate(new Date());
        entity.setStatus(Constant.REFUND_STATUS_1);
        entity.setRefundNo(transactionDO.getIdentifierNo());
        entity.setTransactionNo(transactionDO.getTransactionNo());
        entity.setTransactionId(transactionDO.getId());
        entity.setBeforeBalance(before);
        entity.setAfterBalance(after);

        boolean save = false;
        try {
            save = this.save(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.REFUND_USER_STATUS_ERROR);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.debug("添加退款记录失败");
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if (!save) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.REFUND_USER_STATUS_ERROR);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.debug("添加退款记录失败");
            return result;
        }

        result.setModel(ResultDO.FIRST_MODEL_KEY, getDomain(entity));
        return result;
    }

    @Override
    public ResultDO findInfo(RefundQueryDO query) {
        RefundEntity entity = new RefundEntity();
        ResultDO result = BeanUtilsExtends.copy(entity, query);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        QueryWrapper<RefundEntity> wrapper = new QueryWrapper<>(entity);

        //条件
        if(!TemplateUtils.isEmpty(query.getRefundNo())){
            wrapper.lambda().eq(RefundEntity::getRefundNo, query.getRefundNo());
        }
        if(!TemplateUtils.isEmpty(query.getType())){
            wrapper.lambda().eq(RefundEntity::getType, query.getType());
        }
        if(!TemplateUtils.isEmpty(query.getMerchantId())){
            wrapper.lambda().eq(RefundEntity::getMerchantId, query.getMerchantId());
        }
        if(!TemplateUtils.isEmpty(query.getStatus())){
            wrapper.lambda().eq(RefundEntity::getStatus, query.getStatus());
        }
        if(!TemplateUtils.isEmpty(query.getStartTime())){
            wrapper.lambda().ge(RefundEntity::getRefundDate, query.getStartTime());
        }
        if(!TemplateUtils.isEmpty(query.getEndTime())){
            wrapper.lambda().lt(RefundEntity::getRefundDate, query.getEndTime());
        }

        Page<RefundEntity> page = new Page<>(query.getCurrentPage(),query.getPageSize());
        IPage<RefundEntity> iPage = null;

        List<RefundEntity> list;
        try {
            iPage = baseMapper.selectInfoPage(page, wrapper);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.DEPOSIT_SELECT_ERROR);
            logger.debug("error code：" + ErrorCode.DEPOSIT_SELECT_ERROR.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        List<RefundDO> domainList = getDomainList(iPage.getRecords());

        PageDO<RefundDO> pageDO = new PageDO<>();
        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(domainList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);

        return result;

//        ResultSupport result = new ResultSupport();
//
//        // 创建查询器
//        Page<RefundEntity> page = new Page<>(query.getCurrentPage(), query.getPageSize());
//
//        IPage<RefundEntity> iPage;
//        try {
//            Map<String, Object> map = MapTool.bean2Map(query);
//            // 分页查询
//            iPage = baseMapper.findInfo(page, map);
//        } catch (Exception e) {
//            result.setSuccess(false);
//            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
//            logger.debug("分页查询失败");
//            return result;
//        }
//
//        // 获取查询信息
//        List<RefundDO> doList = getDomainList(iPage.getRecords());
//        PageDO<RefundDO> pageDO = new PageDO<>();
//
//        // 设置分页信息
//        pageDO.setCurrentPage(iPage.getCurrent());
//        pageDO.setPageCount(iPage.getPages());
//        pageDO.setPageSize(iPage.getSize());
//        pageDO.setRowCount(iPage.getTotal());
//        pageDO.setData(doList);
//
//        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
//        return result;
    }

    @Override
    public ResultDO find(RefundQueryDO query) {
        // 创建实体类
        RefundEntity entity = new RefundEntity();
        // 拷贝数据
        ResultDO result = BeanUtilsExtends.copy(entity, query);

        //判断是否拷贝成功
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        // 创建查询器
        QueryWrapper<RefundEntity> wrapper = new QueryWrapper<>(entity);
        Page<RefundEntity> page = new Page<>(query.getCurrentPage(), query.getPageSize());

        IPage<RefundEntity> iPage;
        try {
            // 分页查询
            iPage = baseMapper.selectPage(page, wrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        // 获取查询信息
        List<RefundDO> doList = getDomainList(iPage.getRecords());
        PageDO<RefundDO> pageDO = new PageDO<>();

        // 设置分页信息
        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;
    }


    private RefundDO getDomain(RefundEntity entity) {

        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if (entity == null) {
            return null;
        }
        RefundDO domain = new RefundDO();

        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }

    private List<RefundDO> getDomainList(List<RefundEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<RefundDO> doList = new ArrayList<RefundDO>();

        //判断传入的list的集合的size是否大于0
        if (list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for (RefundEntity entity : list) {

                RefundDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if (domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }


}
